package com.lsh.oms.core.service.other;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.dao.other.OrderRoDetailMapper;
import com.lsh.oms.core.dao.other.OrderRoHeadMapper;
import com.lsh.oms.core.dao.other.OrderShippingHeadMapper;
import com.lsh.oms.core.enums.OrderStatus;
import com.lsh.oms.core.enums.ShippingStatus;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.order.OrderRoDetail;
import com.lsh.oms.core.model.order.OrderRoHead;
import com.lsh.oms.core.model.order.OrderShippingHead;
import com.lsh.oms.core.service.order.OrderUpdateService;
import com.lsh.oms.core.service.tool.Criteria;
import com.lsh.oms.core.service.tool.Pageable;
import com.lsh.oms.core.utils.DateUtil;
import com.lsh.oms.core.utils.IdGenerator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author peter
 */
@Service
@Deprecated
public class RoOrderService {

    @Autowired
    private OrderRoHeadMapper roHeadDao;

    @Autowired
    private OrderShippingHeadMapper shippingDao;

    @Autowired
    private OrderRoDetailMapper detailDao;

    @Autowired
    private OrderUpdateService orderUpdateService;

    @Transactional
    public int create(OrderRoHead head, List<OrderRoDetail> details, boolean allFlag) {
        Long code = IdGenerator.genId();
        head.setReturnOrderId(code);
        int ret = this.roHeadDao.insertSelective(head);
        for (OrderRoDetail detail : details) {
            detail.setReturnOrderId(code);
            this.detailDao.insertSelective(detail);
        }
        if (allFlag) {

            OrderShippingHead osh = new OrderShippingHead();
            osh.setStatus(2);
            int sysTime = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
            osh.setShippingOrderId(head.getShippingOrderId());
            osh.setArrivedAt(sysTime);
            osh.setActivedAt(sysTime);
            osh.setReceiptStatus(1);
            shippingDao.updateStatusByShippingId(osh);
            orderUpdateService.updateOrderStatus(head.getOrderId(), OrderStatus.ORDER_SIGN);
        }

        return ret;
    }


    @Transactional(rollbackFor = RuntimeException.class)
    public boolean createRo4Saas(OrderRoHead head, boolean shippingFlag, boolean orderFlag) {
        Long code = IdGenerator.genId();
        head.setReturnOrderId(code);
        this.roHeadDao.insertSelective(head);
        List<OrderRoDetail> details = head.getDetails();
        for (OrderRoDetail detail : details) {
            detail.setReturnOrderId(code);
            this.detailDao.insertSelective(detail);
        }

        if (shippingFlag) {

            OrderShippingHead osh = new OrderShippingHead();
            osh.setShippingOrderId(head.getShippingOrderId());
            osh.setStatus(ShippingStatus.DELIVERED.getIndex());
            osh.setReceiptStatus(1);
            int sysTime = DateUtil.getCurrentTime();
            osh.setArrivedAt(sysTime);
            osh.setActivedAt(sysTime);

            shippingDao.updateStatusByShippingId(osh);
        }

        if (orderFlag) {

            orderUpdateService.updateOrderStatus(head.getOrderId(), OrderStatus.ORDER_SIGN);
        }

//        head.setDetails(details);

        return true;
    }

    @Transactional
    public int createRo4Cloud(OrderRoHead head) {

        int flag = this.roHeadDao.insertSelective(head);
        for (OrderRoDetail detail : head.getDetails()) {
            detail.setId(null);
            this.detailDao.insertSelective(detail);
        }

        return flag;
    }


    @Transactional
    public int updateByReturnOrderId(OrderRoHead head) {

        int ret = this.roHeadDao.updateByReturnOrderId(head);

        return ret;
    }


    /**
     * 根据返仓单ID 获取 返仓单Detail列表
     *
     * @param returnOrderId
     * @return
     */
    public List<OrderRoDetail> getOrderRoDetailList(Long returnOrderId) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("return_order_id", returnOrderId);
        return detailDao.getOrderRoDetailList(paramMap);
    }

    /**
     * 方法有问题
     *
     * @param orderCode
     * @return
     */
    public OrderRoHead getHead(Long orderCode) {
        List<OrderRoHead> orderRoHeads = roHeadDao.selectByOrderCode(orderCode);

        if (!CollectionUtils.isEmpty(orderRoHeads)) {
            return orderRoHeads.get(0);
        }

        return null;
    }

    public List<OrderRoHead> getRoHeadList(Long orderCode) {
        List<OrderRoHead> orderRoHeads = roHeadDao.selectByOrderCode(orderCode);

        if (CollectionUtils.isEmpty(orderRoHeads)) {
            return Collections.EMPTY_LIST;
        }

        return orderRoHeads;
    }

    /**
     * 方法有问题
     *
     * @param orderCode
     * @return
     */
    public List<OrderRoHead> getOrderRoHead(Long orderCode, Integer returnStatus, boolean fillDetails) {

        List<OrderRoHead> orderRoHeads = roHeadDao.selectByOrderCode(orderCode);
        if (orderRoHeads == null) {
            return null;
        }
        List<OrderRoHead> orderRoHeadList = new ArrayList<>();
        for (OrderRoHead orderRoHead : orderRoHeads) {
            if (orderRoHead.getStatus().equals(returnStatus)) {
                if (fillDetails) {
                    HashMap<String, Object> paramMap = new HashMap<>();
                    paramMap.put("return_order_id", orderRoHead.getReturnOrderId());
                    orderRoHead.setDetails(detailDao.getOrderRoDetailList(paramMap));
                }
                orderRoHeadList.add(orderRoHead);
            }
        }

        return orderRoHeadList;
    }


    public OrderRoHead getRoHeadByReturnOrderId(Long returnOrderId, boolean fillDetails) {
        OrderRoHead orderRoHead = roHeadDao.selectByReturnOrderId(returnOrderId);

        if (orderRoHead == null) {
            return null;
        }

        if (fillDetails) {
            HashMap<String, Object> paramMap = new HashMap<>();
            paramMap.put("return_order_id", returnOrderId);

            orderRoHead.setDetails(detailDao.getOrderRoDetailList(paramMap));
        }

        return orderRoHead;
    }


    /***
     * 根据返仓单获取head信息
     * @param returnOrderId
     * @return
     */
    public OrderRoHead getHeadByReturnOrderId(Long returnOrderId) {

        return roHeadDao.selectByReturnOrderId(returnOrderId);
    }

    public int setValidReturn(OrderRoHead head) {

        return roHeadDao.updateByReturnOrderId(head);
    }

    public int setSoBillCode(OrderRoHead head) {

        return roHeadDao.updateByReturnOrderId(head);
    }

    public List<Long> selectByTimes(Integer startTime, Integer endTime) {

        return roHeadDao.selectByTimes(startTime, endTime);
    }

    public List<Long> findBetween(Integer startTime, Integer endTime) {
        return roHeadDao.findSpecifiedBetween(startTime, endTime, Collections.<Integer>emptySet(), Collections.<Integer>emptySet());
    }

    public List<Long> findSpecifiedBetween(Integer startTime, Integer endTime, Set<Integer> statuses, Set<Integer> types) {
        return roHeadDao.findSpecifiedBetween(startTime, endTime, statuses, types);
    }

    public List<Long> findSpecifiedTypesBetween(Integer startTime, Integer endTime, Set<Integer> types) {
        return roHeadDao.findSpecifiedBetween(startTime, endTime, Collections.<Integer>emptySet(), types);
    }

    public List<Long> findSpecifiedStatusesBetween(Integer startTime, Integer endTime, Set<Integer> statuses) {
        return roHeadDao.findSpecifiedBetween(startTime, endTime, statuses, Collections.<Integer>emptySet());
    }

    public List<Long> selectByParams(List<Long> fids) {

        return roHeadDao.selectByParams(fids);
    }

    public Map<String, Object> findReturnOrderById(Long id) {
        Map<String, Object> head = roHeadDao.findReturnOrderById(id);
        if (MapUtils.isEmpty(head)) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "CAN NOT FIND ANY RECORD BY ID " + id);
        }
        List<Map<String, Object>> items = detailDao.findReturnOrderItemsById(id);
        Map<String, Object> result = new HashMap<>();
        result.put("head", head);
        result.put("detail", items);
        return result;
    }

    public Pageable<OrderRoHead> query(Criteria criteria, long page, long pageLimit) {
        Long count = roHeadDao.countBaseOnCriteria(criteria);
        List<OrderRoHead> result = count > 0
                ? roHeadDao.findBaseOnCriteria(criteria, Pageable.start(page, pageLimit), pageLimit)
                : Collections.<OrderRoHead>emptyList();
        fillDetails(criteria, result);
        return new Pageable<>(result, page, pageLimit, count);
    }

    private boolean detailsRequired(Criteria criteria) {
        return "true".equalsIgnoreCase(criteria.getFirst("details-required"));
    }

    private void fillDetails(Criteria criteria, List<OrderRoHead> result) {
        if (!result.isEmpty() && detailsRequired(criteria)) {
            Multimap<Long, OrderRoDetail> groupedDetails = group(detailDao.findDetailList(ids(result)));
            for (OrderRoHead item : result) {
                item.setDetails(new ArrayList<>(groupedDetails.get(item.getReturnOrderId())));
            }
        }
    }

    private Set<Long> ids(List<OrderRoHead> result) {
        Set<Long> ids = new HashSet<>();
        for (OrderRoHead item : result) {
            ids.add(item.getReturnOrderId());
        }
        return ids;
    }

    private Multimap<Long, OrderRoDetail> group(List<OrderRoDetail> details) {
        Multimap<Long, OrderRoDetail> group = ArrayListMultimap.create();
        for (OrderRoDetail item : details) {
            group.put(item.getReturnOrderId(), item);
        }
        return group;
    }
}
